-- SuperiorM
-- created by panyl
-- 月卡模块

module("SuperiorM", package.seeall);

local superiors = {};

local schedulerId;

-- 载入配置表
local _init = false;
local loadCsv = function()
    if _init then return end
    _init = true;

    local superior_CSV = get_superior_CSV();
    for i = 1, #superior_CSV do
        superiors[superior_CSV[i].level] = superior_CSV[i];
    end
end

-- 模块初始化操作
function init()
    loadCsv();

    EventMgr.removeAll("SuperiorM");
end

-- 判断是否过期了
function isOverdue()
    local data = getSuperiorData();
    if not data then
        -- 如果从来没购买过也当做是过期了
        return true;
    end

    -- 是否过期了
    local serverTime = TimeM.getServerTime();
    local overdue = data["overdue"] or 0;
    if overdue <= serverTime then
        return true;
    end

    return false;
end

-- 获取玩家月卡数据
function getSuperiorData()
    return ME.user.dbase:query("superior");
end

-- 能否购买
function canActiveSuperior()
    if SuperiorM.getSuperiorLevel() > 0 then
        -- 当前还未失效
        return false;
    end

    if BuffDataM.query("charge_reward", 2) == 1 then
        -- 有还未领取的
        return false;
    end

    return true;
end

function query(level, path)
    local m = superiors[level];

    if not m or not path then
        return m;
    end

    return m[path];
end

function getSuperiorLevel()
    local data = ME.user.dbase:query("superior");

    if not data then
        return 0;
    end

    -- 是否过期了
    local serverTime = TimeM.getServerTime();
    local overdue = data["overdue"] or 0;
    if overdue <= serverTime then
        return 0;
    end

    return data["level"];
end

-- 月卡加成
function getSuperiorPrivilege(type)
    -- 如果没有月卡状态
    local level = getSuperiorLevel();
    if level == 0 then
        return;
    end

    return query(level, type);
end

-- 激活月卡
function active()
    -- 如果玩家已经有月卡状态了
    if 0 ~= getSuperiorLevel() then
        return false;
    end

    -- 持续时间
    local duration = query(1, "duration");

    local startTime = TimeM.calcZeroTime();
    local data = {
        ["start_time"] = startTime,
        ["overdue"]    = startTime + duration,
        ["level"]      = 1,
    };

    ME.user.dbase:set("superior", data);

    return true;
end

-- 能否升级招牌
function canUpgrade()
    local curLevel = getSuperiorLevel();
    if curLevel == 0 then
        return false;
    end

    -- 没有下一个等级了
    local nextLevel = curLevel + 1;
    if not query(nextLevel) then
        trace("SuperiorM", "没有下一个等级。");
        return false;
    end

    -- 消耗
    local cost = query(curLevel, "upgrade_cost") or {};
    for attrib, value in pairs(cost) do
        if type(attrib) == "string" and
            ME.user:queryAttrib(attrib) < value then
            -- 属性不足
            trace("SuperiorM", "%s不足，需求%d，当前%d",
                attrib, value, ME.user:queryAttrib(attrib));
            return false;
        elseif type(attrib) == "number" and
            ItemM.getAmount(ME.user, attrib) < value then
            -- 物品不足
            trace("SuperiorM", "%s不足，需求%d，当前%d",
                ItemM.query(attrib, "name"), value, ItemM.getAmount(ME.user, attrib));
            return false;
        end
    end

    -- 暂没有其他要求
    return true;
end

-- 升级
function upgrade()
    -- 先判断
    if not canUpgrade() then
        return false;
    end

    -- 先消耗
    local curLevel = getSuperiorLevel();
    local cost = query(curLevel, "upgrade_cost") or {};
    for attrib, value in pairs(cost) do
        if type(attrib) == "string" then
            -- 扣除属性
            ME.user:costAttrib(attrib, value);
        elseif type(attrib) == "number" then
            -- 扣除物品
            ItemM.costAmount(ME.user, attrib, value);
        else
            assert(false, "something wrong!");
        end
    end

    local data = ME.user.dbase:query("superior", {});

    -- 等级+1，持续时间++
    data["level"] = curLevel + 1;
    data["overdue"] = data["overdue"] + query(curLevel + 1, "duration");

    -- 月卡升级事件
    EventMgr.fire(event.SUPERIOR_UPGRADE);

    -- 告诉服务器升级
    Operation.cmd_upgrade_superior();

    return true;
end

-- 下次奖励时间(倒计时)
function nextBonusTime()
    -- 上次奖励时间
    local data = ME.user.dbase:query("superior");
    local lastBonusTime = data["bonus_time"] or 0;
    local zeroTime = TimeM.calcZeroTime();
    local nextZero = zeroTime + SECONDS_PER_DAY;

    if lastBonusTime < zeroTime then
        return 0;
    end

    -- 下一个0点
    return nextZero - TimeM.getServerTime();
end

-- 能否领取奖励
function cantakeBonus()
    local level = getSuperiorLevel();
    if level == 0 then
        return false;
    end

    local arr = query(level, "daily_bonus");
    if not arr or #arr <= 0 then
        return false;
    end

    -- 上次奖励时间
    local data = ME.user.dbase:query("superior");
    local lastBonusTime = data["bonus_time"] or 0;

    if isSameDay(lastBonusTime, TimeM.getServerTime(), TimeM.getTimeOffsetDifference()) then
        return false;
    end

    return true;
end

-- 每日奖励
function takeDailyBonus()
    local level = getSuperiorLevel();
    if level == 0 then
        return false;
    end

    local arr = query(level, "daily_bonus");
    if not arr or #arr <= 0 then
        return false;
    end

    -- 上次奖励时间
    local data = ME.user.dbase:query("superior");
    local lastBonusTime = data["bonus_time"] or 0;

    if isSameDay(lastBonusTime, TimeM.getServerTime(), TimeM.getTimeOffsetDifference()) then
        return false;
    end

    data["bonus_time"] = TimeM.getServerTime();

    for _, bonus in pairs(arr) do
        BonusM.doBonus(bonus, "superior_daily_bonus");
    end

    -- 告诉服务器
    Operation.cmd_take_superior_bonus();

    -- 抛出事件奖励领取事件
    EventMgr.fire(event.TAKE_SUPERIOR_BONUS, { ["level"] = level, ["bonus"] = arr, } );

    return true;
end

-- 能否领取额外奖励
function canTakeExtraBonus()
    -- 本次的奖励概率
    local data = ME.user.dbase:query("superior");
    local extraBonusRate = data["extra_bonus_rate"] or 100;

    -- 能否领奖
    local result = false;
    local rand = RandomFactoryM.myRandom(ME.user) % 100;
    if extraBonusRate > rand then
        result = true;
    end

    -- 如果本次可以领取，则下次领取概率降低100%，否则提升50%
    if result then
        data["extra_bonus_rate"] = extraBonusRate - 100;
    else
        data["extra_bonus_rate"] = extraBonusRate + 50;
    end

    return result;
end